package com.rtx.edi.platform.ediapi.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rtx.api.utils.MultipleDataSource;
import com.rtx.common.EdiConstant;
import com.rtx.edi.gatway.handle.GatWayHandle;
import com.rtx.edi.platform.custom.bean.EdiCustomProcess;
import com.rtx.edi.platform.custom.mapper.EdiCustomProcessMapper;
import com.rtx.edi.platform.ediapi.bean.EdiApi;
import com.rtx.edi.platform.ediapi.mapper.EdiApiMapper;
import com.rtx.edi.platform.ediapi.service.EdiApiService;
import com.rtx.edi.platform.rule.bean.UpdRule;
import com.rtx.edi.platform.rule.bean.WhseidRule;
import com.rtx.edi.platform.rule.mapper.UpdRuleMapper;
import com.rtx.edi.platform.rule.mapper.WhseidRuleMapper;
import com.rtx.edi.platform.tableconfig.bean.EdiColumnValueConfig;
import com.rtx.edi.platform.tableconfig.bean.EdiTableConfig;
import com.rtx.edi.platform.tableconfig.mapper.EdiColumnValueConfigMapper;
import com.rtx.edi.platform.tableconfig.mapper.EdiTableConfigMapper;


@Service
public class EdiApiServiceImpl extends ServiceImpl<EdiApiMapper, EdiApi> implements EdiApiService{

	@Autowired
	EdiTableConfigMapper ediTableConfigMapper;
	
	@Autowired
	EdiColumnValueConfigMapper ediColumnValueConfigMapper;
	
	@Autowired
	EdiCustomProcessMapper ediCustomProcessMapper;
	
	@Autowired
	WhseidRuleMapper whseidRuleMapper;
	
	@Autowired
	GatWayHandle gatWayHandle;
	
	@Autowired
	UpdRuleMapper updRuleMapper;
	
	
	
	@Override
	public String apitest(String testrequest) {
		JSONObject request = JSON.parseObject(testrequest);
		Long id = request.getLong("id");
		String requestStr = request.getString("request");
		EdiApi ediApi = baseMapper.selectById(id);
		String code = ediApi.getCode();
		String response = gatWayHandle.handleRequest(requestStr, code);
		return response;
	}


	@Override
	public List<Map<String, Object>> queryWhseidRuel() {
		List<WhseidRule> ruleList =	whseidRuleMapper.selectList(Wrappers.lambdaQuery());
		
    	List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
		Map<String,Object> rule = new HashMap<String, Object>();
		rule.put("label", "");
		rule.put("value", "");
		list.add(rule);
		
		for(WhseidRule whseidRule:ruleList) {
			Map<String,Object> temp = new HashMap<String, Object>();
			temp.put("label", whseidRule.getName());
			temp.put("value", whseidRule.getId()+"");
			list.add(temp);
		}
		
		return list;
		
	}
	

	@Override
	public List<Map<String, Object>> queryUpdRuel() {
		List<UpdRule> ruleList = updRuleMapper.selectList(Wrappers.lambdaQuery());
		
    	List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
		Map<String,Object> rule = new HashMap<String, Object>();
		rule.put("label", "");
		rule.put("value", "");
		list.add(rule);
		
		for(UpdRule updRule:ruleList) {
			Map<String,Object> temp = new HashMap<String, Object>();
			temp.put("label", updRule.getName());
			temp.put("value", updRule.getId()+"");
			list.add(temp);
		}
		return list;
	}


	@Override
	public void selectList(Page<EdiApi> pageParam, EdiApi po) {
		LambdaQueryWrapper<EdiApi> query = Wrappers.lambdaQuery();
		query.like(po.getName() != null,EdiApi::getName, po.getName());
		query.eq(po.getType() !=null, EdiApi::getType,po.getType());
		query.eq(po.getMaintable() !=null, EdiApi::getMaintable,po.getMaintable());
		query.eq(po.getSubtable() !=null, EdiApi::getSubtable,po.getSubtable());
        baseMapper.selectPage(pageParam, query);
	}

	@Override
	public void configEdiCustomProcess(String requestStr) {
		JSONObject request = JSON.parseObject(requestStr);
		Long id = request.getLong("id");
		List<String> allList = new ArrayList<String>();
		List<String> validate = Optional.ofNullable(request.getJSONArray(EdiConstant.CUSTOM_PROCESS_VALIDATE)).orElse(new JSONArray()).toJavaList(String.class);
		List<String> prehandle =Optional.ofNullable(request.getJSONArray(EdiConstant.CUSTOM_PROCESS_PREHANDLE)).orElse(new JSONArray()).toJavaList(String.class);
		List<String> customafter = Optional.ofNullable(request.getJSONArray(EdiConstant.CUSTOM_PROCESS_CUSTOMAFTER)).orElse(new JSONArray()).toJavaList(String.class);
		allList.addAll(validate);
		allList.addAll(prehandle);
		allList.addAll(customafter);
		String customids = "";
		if(allList.size() > 0) {
			customids = allList.stream().collect(Collectors.joining(","));
		}
		LambdaUpdateWrapper<EdiApi> upd = Wrappers.lambdaUpdate();
		upd.eq(EdiApi::getId, id);
		upd.set(EdiApi::getCustomids, customids);
		baseMapper.update(null, upd);
	}

	@Override
	public void addAndInitEdiApi(EdiApi dto) {
		LambdaQueryWrapper<EdiApi> query = Wrappers.lambdaQuery();
		query.eq(EdiApi::getCode, dto.getCode());
	    boolean exists = baseMapper.exists(query);
	    Assert.isTrue(!exists,"接口编码-"+dto.getCode()+"-已经存在");
		
		baseMapper.insert(dto);
		
		Map<String,Object> data = intTableValueConfigAndRequestData(dto);
		
		saveTableValueConfig(data);
		
		updateRequest(dto,data);
	}
	
	//保存
	private void saveTableValueConfig(Map<String,Object> map) {
		List<EdiTableConfig> tableConfigList = (List<EdiTableConfig>) map.get("tableConfigList");
		for(EdiTableConfig config:tableConfigList) {
			ediTableConfigMapper.insert(config);
			for(EdiColumnValueConfig ediColumnValueConfig:config.getColumnvalue()) {
				ediColumnValueConfig.setEditableconfigid(config.getId());
				ediColumnValueConfigMapper.insert(ediColumnValueConfig);
			}
		}
	};

	/**
	 * 初始化报文与表字段配置
	 */
	public Map<String,Object> intTableValueConfigAndRequestData(EdiApi dto) {
		LambdaQueryWrapper<EdiApi> query = Wrappers.lambdaQuery();
		query.eq(EdiApi::getCode, dto.getCode());
		EdiApi ediapi =	baseMapper.selectOne(query);
		//响应数据
		Map<String,Object> data = new HashedMap<String, Object>();
		//请求报文
		JSONObject requestJSON = null;
		//假如为标准接口 初始标准报文 将通过表字段与表名称填充生成
		if(EdiConstant.EDI_API_TYPE_STD.equals(ediapi.getType())) {
			requestJSON = new JSONObject();
		}else {
			requestJSON = JSON.parseObject(dto.getRequest());
		}
		//表配置信息
		List<EdiTableConfig> tableConfigList = new ArrayList<EdiTableConfig>();
		
		if(StringUtils.hasLength(ediapi.getMaintable())) {
			EdiTableConfig mainEdiTableConfig = new EdiTableConfig();
			mainEdiTableConfig.setApiid(ediapi.getId());
			mainEdiTableConfig.setName(ediapi.getMaintable());
			mainEdiTableConfig.setRequestrootnode(EdiConstant.REQUEST_ROOT_NODE);
			List<EdiColumnValueConfig> columnvalueConfigList = new ArrayList<EdiColumnValueConfig>();
			List<Map<String,String>> columns = queryColumnsFromTable(ediapi.getDatasource(),ediapi.getMaintable());
			
			for(Map<String,String> column:columns) {
				String columnname = column.get("Field").toLowerCase();
				String descr =Optional.ofNullable(column.get("Comment")).orElse("") ;
				EdiColumnValueConfig ediColumnValueConfig = new EdiColumnValueConfig();
				ediColumnValueConfig.setColumnname(columnname);
				ediColumnValueConfig.setColumndescr(descr);
				ediColumnValueConfig.setEditableconfigid(mainEdiTableConfig.getId());
				if(EdiConstant.EDI_API_TYPE_STD.equals(ediapi.getType())) {
					ediColumnValueConfig.setRequestvaluepath(columnname);
					requestJSON.put(columnname, descr);
				}
				columnvalueConfigList.add(ediColumnValueConfig);
			}
			mainEdiTableConfig.setColumnvalue(columnvalueConfigList);
			
			tableConfigList.add(mainEdiTableConfig);
		}
		
		if(StringUtils.hasLength(ediapi.getSubtable())) {
			for(String subtable:ediapi.getSubtable().split(",")) {
				List<JSONObject> subJsonList = new ArrayList<JSONObject>();
				JSONObject subjson = new JSONObject();
				
				EdiTableConfig subEdiTableConfig = new EdiTableConfig();
				subEdiTableConfig.setApiid(ediapi.getId());
				subEdiTableConfig.setName(subtable);
				subEdiTableConfig.setRequestrootnode(subtable);
				
				List<EdiColumnValueConfig> columnvalueConfigList = new ArrayList<EdiColumnValueConfig>();
				List<Map<String,String>> columns = queryColumnsFromTable(ediapi.getDatasource(),subtable);
				for(Map<String,String> column:columns) {
					
					String columnname = column.get("Field").toLowerCase();
					String descr = column.get("Comment");
					EdiColumnValueConfig ediColumnValueConfig = new EdiColumnValueConfig();
					ediColumnValueConfig.setColumnname(columnname);
					ediColumnValueConfig.setColumndescr(descr);
					ediColumnValueConfig.setEditableconfigid(subEdiTableConfig.getId());
					
					if(EdiConstant.EDI_API_TYPE_STD.equals(ediapi.getType())) {
						ediColumnValueConfig.setRequestvaluepath(subtable+"数组."+columnname);
						subjson.put(columnname, descr);
					}
					columnvalueConfigList.add(ediColumnValueConfig);
				}
				
				if(EdiConstant.EDI_API_TYPE_STD.equals(ediapi.getType())) {
					subJsonList.add(requestJSON);
					requestJSON.put(subtable, subJsonList);
				}
				subEdiTableConfig.setColumnvalue(columnvalueConfigList);
				
				tableConfigList.add(subEdiTableConfig);
			}
		}
		data.put("tableConfigList", tableConfigList);
		data.put("request", requestJSON.toJSONString());
		return data;
	}
	
	
	List<Map<String,String>> queryColumnsFromTable(String datasourcekey,String tablename){
		MultipleDataSource.setDataSourceKey(datasourcekey);
		String sql = "show full columns from "+tablename;
		List<Map<String, String>> list =  baseMapper.queryAllColumnsByTableName(sql);
		MultipleDataSource.ClearDataSourceKey();
		return list;
	}
	
	//更新报文字段
	private void updateRequest(EdiApi po,Map<String,Object> data) {
		LambdaUpdateWrapper<EdiApi> upd = Wrappers.lambdaUpdate();
		upd.eq(EdiApi::getId, po.getId());
		upd.set(EdiApi::getRequest, data.get("request")+"");
		baseMapper.update(null, upd);
	}

	@Override
	public Map<String, Object> queryConfigEdiCustomProcess(EdiApi dto) {
		Map<String, Object> result = new HashMap<>();
		List<EdiCustomProcess> list = ediCustomProcessMapper.selectList(Wrappers.lambdaQuery());
		result.put("all"+EdiConstant.CUSTOM_PROCESS_VALIDATE, list.stream().filter(temp->EdiConstant.CUSTOM_PROCESS_VALIDATE.equals(temp.getType())).collect(Collectors.toList()));
		result.put("all"+EdiConstant.CUSTOM_PROCESS_PREHANDLE, list.stream().filter(temp->EdiConstant.CUSTOM_PROCESS_PREHANDLE.equals(temp.getType())).collect(Collectors.toList()));
		result.put("all"+EdiConstant.CUSTOM_PROCESS_CUSTOMAFTER, list.stream().filter(temp->EdiConstant.CUSTOM_PROCESS_CUSTOMAFTER.equals(temp.getType())).collect(Collectors.toList()));
		
		List<Long> validate = new ArrayList<>();
		List<Long> prehandle = new ArrayList<>();
		List<Long> customafter = new ArrayList<>();
		
		EdiApi edifapi = baseMapper.selectById(dto.getId());
		if(StringUtils.hasLength(edifapi.getCustomids())) {
			
			List<String> customIds =Arrays.asList(Optional.ofNullable(edifapi.getCustomids()).orElse("").split(","));
			for(String id:customIds) {
				Optional<EdiCustomProcess> process = 	list.stream().filter(temp->id.equals(temp.getId()+"")).findFirst();
				if(EdiConstant.CUSTOM_PROCESS_VALIDATE.equals(process.get().getType())) {
					validate.add(Long.parseLong(id));
				}
				if(EdiConstant.CUSTOM_PROCESS_PREHANDLE.equals(process.get().getType())) {
					prehandle.add(1l);
				}
				if(EdiConstant.CUSTOM_PROCESS_CUSTOMAFTER.equals(process.get().getType())) {
					customafter.add(Long.parseLong(id));
				}
			}

		}
		
		result.put(EdiConstant.CUSTOM_PROCESS_VALIDATE.toLowerCase(), validate);
		result.put(EdiConstant.CUSTOM_PROCESS_PREHANDLE.toLowerCase(), prehandle);
		result.put(EdiConstant.CUSTOM_PROCESS_CUSTOMAFTER.toLowerCase(), customafter);
		return result;
	}
	
	
	/**
	 *	重新生成报文
	 * @return
	 */
	public String buildStdRequestJson(EdiApi ediai) {
		JSONObject rootNode = new JSONObject();
		
		LambdaQueryWrapper<EdiTableConfig> qw = Wrappers.lambdaQuery();
		qw.eq(EdiTableConfig::getApiid, ediai.getId());
		List<EdiTableConfig> list = ediTableConfigMapper.selectList(qw);
		
		//没有配置表返回空
		if(null== list || list.size() < 1) {
			return rootNode.toJSONString();
		}
		List<EdiTableConfig> requesttableList = list.stream().filter(temp->"true".equals(temp.getActiverequest())).collect(Collectors.toList());
		
		//没有作为报文节点的表
		if(requesttableList.size() < 1) {
			return rootNode.toJSONString();
		}
		
		//查找根节点的表
		List<EdiTableConfig> rootNodeTableList = list.stream().filter(temp->-1 == temp.getParentnode()).collect(Collectors.toList());
		if(rootNodeTableList == null || rootNodeTableList.size() < 1) {
			return rootNode.toJSONString();
		}
		
		for(EdiTableConfig rootNodeTable:rootNodeTableList) {
			//获取根节点所有字段并且
			LambdaQueryWrapper<EdiColumnValueConfig> cvcQw = Wrappers.lambdaQuery();
			cvcQw.eq(EdiColumnValueConfig::getEditableconfigid, rootNodeTable.getId());
			List<EdiColumnValueConfig> cvcList =	ediColumnValueConfigMapper.selectList(cvcQw);
			List<EdiColumnValueConfig> activeRequestList =	cvcList.stream().filter(temp->"true".equals(temp.getActiverequest())).collect(Collectors.toList());
			//根节点的表没有中没有要成为报文节点的字段则直接返回
			if(activeRequestList.size()<1) {
				return rootNode.toJSONString();
			}
			//将值设置到根节点中
			for(EdiColumnValueConfig cvc:activeRequestList) {
				rootNode.put(cvc.getColumnname(),Optional.ofNullable(cvc.getColumndescr()).ofNullable(""));
			}
		}

		
		//查找二级节点
		List<Integer> rootids = rootNodeTableList.stream().map(temp->temp.getId().intValue()).collect(Collectors.toList());
		List<EdiTableConfig> secondNodeTableList = list.stream().filter(temp->rootids.contains(temp.getParentnode())).collect(Collectors.toList());
		//二级节点的表不存在 直接返回根节点填充的报文
		if(secondNodeTableList.size() < 1) {
			return rootNode.toJSONString();
		}
		
		for(EdiTableConfig tableConfig:secondNodeTableList) {
			fillNodeByConfig(tableConfig,requesttableList,rootNode);
		}
		return rootNode.toJSONString();
	}
	
	//将字段名称填充到节点中
	private void fillNodeByConfig(EdiTableConfig tableConfig,List<EdiTableConfig> requesttableList,JSONObject rootNode) {
		List<JSONObject> subNodeList = new ArrayList<JSONObject>();
		JSONObject subNode = new JSONObject();
		//获取根节点所有字段并且
		LambdaQueryWrapper<EdiColumnValueConfig> cvcQw = Wrappers.lambdaQuery();
		cvcQw.eq(EdiColumnValueConfig::getEditableconfigid, tableConfig.getId());
		List<EdiColumnValueConfig> cvcList =	ediColumnValueConfigMapper.selectList(cvcQw);
		List<EdiColumnValueConfig> activeRequestList =	cvcList.stream().filter(temp->"true".equals(temp.getActiverequest())).collect(Collectors.toList());
		
		//根节点的表没有中没有要成为报文节点的字段则直接返回
		if(activeRequestList.size()<1) {
			return;
		}
		
		for(EdiColumnValueConfig cvc:activeRequestList) {
			subNode.put(cvc.getColumnname(),Optional.ofNullable(cvc.getColumndescr()).ofNullable(""));
		}
		subNodeList.add(subNode);
		
		List<EdiTableConfig> childList = requesttableList.stream().filter(temp->tableConfig.getId() == temp.getParentnode()).collect(Collectors.toList());
		if(childList.size() > 0) {
			for(EdiTableConfig child:childList) {
				fillNodeByConfig(child,requesttableList,subNode);
			}
		}
		
		rootNode.put(tableConfig.getName(), subNodeList);
	}
}
